#!/usr/bin/env python2
#-*- coding: utf-8 -*-
import xlrd, re, smtplib, threading
from email.mime.text import MIMEText
from ConfigParser import *
from ui import *
from excep import *

#reload(sys)
#sys.setdefaultencoding('utf-8')

xdlg = None

def SetLogDlg(dlg):
    global xdlg
    xdlg = dlg

def WrtLog(msg):
    global xdlg
    if xdlg:
        xdlg.m_textlog.AppendText(u'%s' % msg)

def GetConfig(configf = u'config.ini'):
    #读取配置文件
    secs = [u'global', u'resource', u'templet']
    cfgs = {}
    cfg = ConfigParser()
    cfg.readfp(open(configf, u'r'))
    for sec in secs:
        t = {}
        for (k, v) in cfg.items(sec):
            t[k] = v
        cfgs[sec] = t
    #返回配置信息
    return cfgs

def CheckLink(cfgs):
    cfg = cfgs[u'global']
    try:
        smtp = smtplib.SMTP()
        smtp.connect(cfg[u'smtphost'])
        smtp.login(cfg[u'username'], cfg[u'password'])
        smtp.quit()
    except Exception, e:
        raise MyWarn(u'CheckLink: 检查链接失败(%s)!\n' % e)

def SendMail(cfgs, mail):
    retVal = False
    while (not retVal):
        try:
            cfg = cfgs[u'global']
            body = MIMEText(mail[u'content'], u'html', u'utf-8')
            body[u'From'] = cfg[u'username']
            body[u'Subject'] = mail[u'subject']
            #send mail to server
            smtp = smtplib.SMTP(timeout = 15)
            smtp.connect(cfg[u'smtphost'])
            smtp.login(cfg[u'username'], cfg[u'password'])
            smtp.sendmail(cfg[u'username'], mail[u'to'], body.as_string())
            smtp.quit()
            retVal = True
        except Exception, e:
            print e
            #raise MyWarn(u'SendMail: 发送邮件失败(%s@%s)!\n' % (mail[u'subject'], e))

def Alert(msg):
    dlg = wx.MessageDialog(None, msg, u'消息',wx.OK) 
    dlg.ShowModal()

def GetMailAddrs(cfgs):
    mlist   = {}
    sht     = None
    fMail   = None

    try:
        fMail = cfgs[u'global'][u'addrlist']
    except Exception, e:
        raise MyWarn(u'GetMailAddrs: 读取配置失败(%s)!\n' % e)
    
    
    try:
        workbook = xlrd.open_workbook(fMail)
        sht = workbook.sheet_by_index(0)
    except Exception, e:
        raise MyWarn(u'GetMailAddrs: 打开邮件数据文件错误(%s)!\n' % e)
    
    for row in range(1, sht.nrows):
        name = (u'%s' % sht.cell(row, 0).value).strip()
        addr = (u'%s' % sht.cell(row, 1).value).strip()
        if (name != u'') and (re.match(r'^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$', addr)):
            mlist[name] = addr
        else:
            raise MyWarn(u'GetMailAddrs: 错误的邮件地址(%s : %s)!\n' % (name, addr))
    return mlist

def GetTemplet(fTemplet):
    #读取模板文件
    try:
        t = (lambda f:(f.read(), f.close()))(open(fTemplet, u'r'))[0]
        return t.decode(u'utf-8')
    except Exception, e:
        raise MyWarn(u'GetTemplet: 获取模板文件出错：%s!\n' % e)

def GetFormat(s):
    ret = {
        u'row'   : None,
        u'col'   : None,
        u'start' : None,
        u'end'   : None,
        u'format': None,
        u'type'  : u's',
    }
    
    m = re.match(r'\((\w+),(\d+)\)', s)
    if m:
        x = m.group(1)
        if x != u'x':
            ret[u'row'] = int(x)
        else:
            ret[u'row'] = x
        ret[u'col'] = int(m.group(2))
    else:
        raise Exception(u'bad format')
    
    m = re.search(r'\[(\d+):(.*)\]', s)
    if m:
        ret[u'start'] = int(m.group(1))
        ret[u'end'] = int(m.group(2))
    m = re.search(r",'(%.*(\w))'", s)
    if m:
        ret[u'format'] = m.group(1)
        ret[u'type']   = m.group(2)
    return ret

#list(set(re.findall(r'<\?(\w+)\?>', templet)))
def GetFormats(cfg):
    fmts = {}
    for (k, v) in cfg[u'templet'].items():
        try:
            fmts[k] = GetFormat(v)
        except Exception, e:
            raise MyWarn(u'GetFormats: 解析模板配置失败(`%s@[%s]`格式不对)!\n' % (k, v))
    return fmts

def GetFloatStr(f, fmt):
    import math as m
    if (m.floor(f) < f):
        return fmt % f
    else:
        return u'%d' % f

def GetCellVal(sht, nrow, fmt):
    row = 0
    col = 0
    val = None
    if fmt[u'row'] == u'x':
        row = nrow
    else:
        row = fmt[u'row']
    col = fmt[u'col']
    val = sht.cell(row, col).value

    if type(fmt[u'start']) == int and type(fmt[u'end']) == int:
        val = val[fmt[u'start'] : fmt[u'end']]
        
    if fmt[u'type'] == u'd':
        val = str(int(val))
    elif fmt[u'type'] == u'f':
        val = GetFloatStr(float(val), fmt[u'format'])

    if type(val) == unicode:
        return val

    return str(val)

def CheckTemplet(templet, fmts):
    for k in list(set(re.findall(r'<\?(\w+)\?>', templet))):
        fmts[k]

def CheckMails(cfg, mails, sals):
    keyw = cfg[u'global'][u'keyword']
    for sal in sals:
        t = sal[keyw]
        mails[t]

#获取薪资文件解析后的所有行信息
def GetSalaries(cfg, fmts, salaryf):
    ret     = []
    sht     = None
    try:
        rowskip = int(cfg[u'global'][u'rowskip'])
    except Exception, e:
        raise MyWarn(u'GetSalaries: 读取配置rowskip失败：%s!\n' % e)

    try:
        workbook = xlrd.open_workbook(salaryf)
        sht = workbook.sheet_by_index(0)
    except Exception, e:
        raise MyWarn(u'GetSalaries: 打开薪资文件失败：%s!\n' % e)

    #解析薪资文件
    for row in range(rowskip, sht.nrows):
        t = {}
        try:
            for (k, v) in fmts.items():
                t[k] = GetCellVal(sht, row, v)
            ret.append(t)
        except Exception, e:
            WrtLog(u'GetSalaries: 获取行警告(%s)!\n' % e)
            pass
    return ret

def GetMail(cfgs, templet, addrs, sal, tips = u''):
    #生成邮件信息
    t       = {}
    cfg     = None
    keyw    = None
    subj    = None
    
    try:
        cfg    	= cfgs[u'global']
        keyw    = cfg[u'keyword']
        subj    = cfg[u'subject']
    except Exception, e:
        raise MyWarn(u'GetMail: 读取配置失败：%s!\n' % e)
    
    content = templet

    k = None
    try:
        k = sal[keyw]
    except Exception, e:
        raise MyWarn(u'GetMail: Keyword(%s)不存在!\n' % keyw)
    
    try:
        t[u'to'] = addrs[k]
    except Exception, e:
        raise MyWarn(u'GetMail: 没有匹配"%s"的邮件地址!\n' % k)
    
    #生成邮件主题
    subj = unicode(subj, u'GB2312')
    for k in re.findall(r'<\?(\w+)\?>', subj):
        tag = None
        try:
            tag = sal[k]
        except Exception, e:
            raise MyWarn(u'GetMail: 未找到邮件主题所需标签`%s`!\n' % k)
        subj = subj.replace(u'<?%s?>' % k, tag)
    t[u'subject'] = subj

    #生成邮件主体
    for k in list(set(re.findall(r'<\?(\w+)\?>', templet))):
        v = None
        try:
            v = sal[k]
        except Exception, e:
            raise MyWarn(u'GetMail: 解析模板标签`%s`错误(%s)!\n' % (k, e))
        
        try:
            v = u'' + v
        except Exception, e:
            v = str(v)

        content = content.replace(u'<?%s?>' % k, v)
    
    if (tips != u''):
        content = u"""
            <div>%s</div>
            <div>
                <p><B>*备注：</B>%s</p>
            </div>
            """ % (content, tips)
    t[u'content'] = content
    return t

def GetMails(cfg, templet, addrs, sals, tips = u''):
    ret = []
    for sal in sals:
        ret.append(GetMail(cfg, templet, addrs, sal, tips))
    return ret

class ProcThread(threading.Thread):
    def __init__(self, dlg):
        threading.Thread.__init__(self)
        self.dlg = dlg
        
    def run(self):
        WrtLog(u'\n-------------------------\n')
        WrtLog(u'解析薪资文件: %s\n' % (self.dlg.salaryf, ))
        self.dlg.m_textTips.Disable()
        try:
            ret = []
            templet = GetTemplet(self.dlg.templetf)
            #print templet
            addrs   = GetMailAddrs(self.dlg.cfgs)
            #print addrs
            fmts    = GetFormats(self.dlg.cfgs)
            #print fmts
            sals    = GetSalaries(self.dlg.cfgs, fmts, self.dlg.salaryf)
            #print sals
            ret = GetMails(self.dlg.cfgs, templet, addrs, sals, self.dlg.tips)
            
            if (len(ret) != 0):
                self.dlg.mlist = ret
                for t in ret:
                    WrtLog(u' >M: %15s\n' % t[u'subject'])
                WrtLog(u'***** 共 %d 封邮件\n' % len(ret))
                self.dlg.m_btnmailer.Enable()
        except MyWarn, w:
            WrtLog(w.msg)
            Alert(w.msg)
        except Exception, e:
            msg = u'ProcThread: 未知错误(%s)!\n' % e
            WrtLog(msg)
            Alert(msg)
        self.dlg.m_textTips.Enable()
        
        WrtLog(u'-------------------------\n\n')
    
    def __del__( self ):
        pass

class SendThread(threading.Thread):
    def __init__(self, dlg):
        threading.Thread.__init__(self)
        self.dlg = dlg
        
    def run(self):
        WrtLog(u'\n-------------------------\n')
        self.dlg.m_btnmailer.Disable()
        self.dlg.m_gauge.SetRange(len(self.dlg.mlist))
        self.dlg.m_gauge.SetValue(0)

        try:
            CheckLink(self.dlg.cfgs)
                
            i = 0
            WrtLog(u'邮件发送中')
            for mail in self.dlg.mlist:
                try:
                    SendMail(self.dlg.cfgs, mail)
                except MyWarn, w:
                    WrtLog(u'\nSendThread: [%s] 发送失败(%s)\n' % (mail[u'subject'], w))
                    pass
                i += 1
                WrtLog(u'.')
                self.dlg.m_gauge.SetValue(i)
            msg = u'\n邮件发送完毕！\n共%d封邮件，发送成功%d封。\n' % (len(self.dlg.mlist), i)
            WrtLog(msg)
            Alert(msg)
        except MyWarn, w:
            WrtLog(w.msg)
            Alert(w.msg)
        
        #清除数据
        self.dlg.mlist = []
        WrtLog(u'-------------------------\n\n')
    
    def __del__( self ):
        pass
